package com.jblog.core.service.blog.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jblog.common.page.Pagination;
import com.jblog.common.page.common.PageType;
import com.jblog.core.CoreUtil;
import com.jblog.core.dao.blog.PostDao;
import com.jblog.core.dao.blog.PostTagLinkDao;
import com.jblog.core.model.blog.Post;
import com.jblog.core.model.blog.PostTagLink;
import com.jblog.core.model.blog.Tag;
import com.jblog.core.model.blog.param.PostParam;
import com.jblog.core.service.blog.PostService;
import com.jblog.core.service.blog.TagService;

@Service
public class PostServiceImpl implements PostService {
    
    @Autowired private PostDao postDao;
    @Autowired private PostTagLinkDao postTagLinkDao;
    @Autowired private TagService tagService;
    
    public Post findById(Long id) {
        return findOne(new PostParam(id));
    }

    @Override
    public Post findByAlisa(String s) {
        return findOne(new PostParam(s));
    }
    
    @Override
    public List<Post> findPreviousAndNext(PostParam p) {
        List<Post> posts = new ArrayList<Post>();
        posts.addAll(postDao.getPrevious(p));
        posts.addAll(postDao.getNext(p));
        
        return posts;
    }

    @Override
    public Long count(PostParam p) {
        return postDao.count(p);
    }

    @Override
    public Long findMaxId() {
        return postDao.getMaxId();
    }

    @Override
    public void enDisable(Post e, boolean able) {
        if (!CoreUtil.checkStatus(e.getStatus(), able)) {
            postDao.update(new Post(e.getId(), CoreUtil.toStatus(able)));
        }
    }
    
    @Override
    public List<Post> findByParam(PostParam p) {
        return postDao.byParam(p);
    }


    @Override
    @SuppressWarnings("rawtypes")
    public Pagination findByParamByPage(PostParam p) {
        Long totalCount = count(p);
        Pagination page = new Pagination(p.getPageNo(), p.getPageSize(), totalCount, PageType.CONSECUTIVE);
        if (!StringUtils.isBlank(p.getCssClass())) {
            page.setCssClass(p.getCssClass());
        }
        if (totalCount < 1L) {
            page.setDatas(new ArrayList());
            return page;
        } 
        page.setDatas(findByParam(p));
        
        return page;
    }

    @Override
    public void save(Post e) {
        postDao.save(e);
        dealSavePostTagLink(e, toNewTags(e.getTags()));
    }

    @Override
    public void update(Post e) {
        dealUpdatePost(e);
        postDao.update(e);
    }

    @Override
    public void delete(Long id) {
        //Don't suggest to delete operation
        postTagLinkDao.deleteByPostPk(id);
        postDao.deleteByPk(id);
    }
    
    private Post findOne(PostParam p) {
        List<Post> es = findByParam(p);
        if (null != es && es.size() == 1) {
            return es.get(0);
        } 
        return null;
    }
    
    private List<Tag> toNewTags(final List<Tag> tags) {
        List<Tag> newTags = new ArrayList<Tag>();
        if (null != tags && tags.size() > 0) {
            for (Tag t : tags) {
                if (null == t.getId()) {
                    //means a new tag, should save to DB and return the primary key 'id'
                    tagService.save(t);
                } 
                newTags.add(t);
            }
        }
        return newTags;
    }
    
    private void dealUpdatePost(final Post post) {
        //first delete all tags link and add new link
        dealRemovePostTagLink(post);
        dealSavePostTagLink(post, toNewTags(post.getTags()));
    }
    private void dealSavePostTagLink(final Post p, final List<Tag> tags) {
        if (tags.size() > 0) {
            List<PostTagLink> es = new ArrayList<PostTagLink>();
            for (Tag t : tags) {
                es.add(new PostTagLink(p, t));
            }
            postTagLinkDao.saveBatch(es);
        }
    }
    
    private void dealRemovePostTagLink(final Post post) {
        postTagLinkDao.deleteByPostPk(post.getId());
    }
}
